﻿/** \file
* \par Subversion URL:
* \$URL: http://planar-rendering.googlecode.com/svn/trunk/frontend/src/Program.cs $
* \version \$Rev: 78 $
* \date    \$Date: 2009-04-20 09:47:39 +0000 (Mon, 20 Apr 2009) $
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Frontend
{
	/// <summary>
	/// The main application class.
	/// </summary>
	static class Program
	{
		/// <summary>
		/// Unmanaged win32 call to load a DLL.
		/// </summary>
		/// <param name="lpLibFileName">The DLL file name.</param>
		/// <returns>A handle to the loaded module.</returns>
		[DllImport("kernel32", SetLastError = true)]
		public extern static IntPtr LoadLibrary(string lpLibFileName);

		/// <summary>
		/// Unmanaged win32 call to unload a DLL.
		/// </summary>
		/// <param name="hLibModule">A handle to the library to unload.</param>
		/// <returns>True for success.</returns>
		[DllImport("kernel32", SetLastError = true)]
		public extern static bool FreeLibrary(IntPtr hLibModule);

		/// <summary>The fractal generator instance.</summary>
		public static Generator generator = new Generator();
		/// <summary>The orthagonal projection render target.</summary>
		public static OrthTarget targetOrth = new OrthTarget(generator);
		/// <summary>The matlab file render target.</summary>
		public static MatlabTarget targetMatlab = new MatlabTarget(generator);
		/// <summary>The main form instance.</summary>
		static MainForm form;

		/// <summary>The list of function factories.</summary>
		public static List<AbstractFunctionFactory> funcsAvailable = new List<AbstractFunctionFactory>
		{
			new FunctionFactory<func_s>(),
			new FunctionFactory<func_zabscomps>(),
			new FunctionFactory<func_zpow2>(),
			new FunctionFactory<func_zpowd>(),
			new FunctionFactory<func_zpluss>(),
			new FunctionFactory<func_zplusc>()
		};

		/// <summary>The DLL handle.</summary>
		public static IntPtr hlib;

		/// <summary>The matlab file name.</summary>
		public static string matlabFilename;

		/// <summary>
		/// The program entry point. Starts the main form.
		/// </summary>
		[STAThread]
		static void Main()
		{
			hlib = LoadLibrary("engine.dll");
			if (hlib == IntPtr.Zero)
			{
				int error = Marshal.GetLastWin32Error();
				throw new Exception("Failed to load engine.dll, win32 error " + error.ToString());
			}

			for (int f = 0; f < funcsAvailable.Count; f++)
				funcsAvailable[f].enumIndex = f;

			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);

			form = new MainForm();
			Application.Run(form);

			if (!FreeLibrary(hlib))
			{
				int error = Marshal.GetLastWin32Error();
				throw new Exception("Could not unload engine.dll, win32 error " + error.ToString());
			}
		}

		/// <summary>
		/// Start matlab data generation.
		/// </summary>
		public static void GenerateMatlab()
		{
			targetMatlab.matlabFile = new StreamWriter(matlabFilename);
			BeginGenerate(targetMatlab);
		}

		/// <summary>
		/// Start orthagonal projection data generation.
		/// </summary>
		public static void GenerateOrth()
		{
			BeginGenerate(targetOrth);
		}

		/// <summary>
		/// Begin the generation. Sets up the form and starts the generator.
		/// </summary>
		/// <param name="activeTarget">The target to use.</param>
		static void BeginGenerate(Target activeTarget)
		{
			form.SetProgressMax(generator.Begin(activeTarget));
			generator.Run();
		}

		/// <summary>
		/// Increment the progress bar.
		/// </summary>
		public static void IncrementProgress()
		{
			form.IncrementProgress();
		}

		/// <summary>
		/// End the generation session.
		/// </summary>
		public static void EndGenerate()
		{
			form.EndGenerate();
		}

		/// <summary>
		/// Get an automatic filename based on the date and time.
		/// </summary>
		/// <returns>The filename.</returns>
		static public string AutoMatlabFilename()
		{
			string now = DateTime.Now.ToString("yy'-'MM'-'dd' 'HH'.'mm'.'ss");
			return now + ".bin";
		}

		/// <summary>
		/// Add a new function.
		/// </summary>
		/// <param name="f">The factory index of the function to add.</param>
		/// <returns>The new function object.</returns>
		static public Function AddFunction(int f)
		{
			return generator.AddFunction(funcsAvailable[f]);
		}

		/// <summary>
		/// Remove a function.
		/// </summary>
		/// <param name="i">The generator index of the function to remove.</param>
		static public void RemoveFunction(int i)
		{
			generator.RemoveFunction(i);
		}
	}
}
